
/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.sychip.fhc.app.wsn.screen


import androidx.lifecycle.viewModelScope
import com.fhc.base.EventType
import com.fhc.base.FhcFlowEventBus
import com.fhc.base.FlowEventBusData
import com.sychip.fhc.MainApplication
import com.sychip.fhc.app.data.repo.WsnDeviceRepo
import com.sychip.fhc.app.data.repo.WsnDeviceRssiRepo
import com.sychip.fhc.app.data.repo.WsnRssiHisRepo
import com.sychip.fhc.app.data.source.dto.WsnDeviceRssiDto
import com.sychip.fhc.app.pref.PrefDataStoreIf
import com.sychip.fhc.base.BaseAppViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject


/**
 * ViewModel for the WsnList screen.
 *
 * @property rssiRepo
 * @constructor
 *
 * @param app
 */
@HiltViewModel
open class WsnBaseViewModel @Inject constructor(
    app : MainApplication,
    open val prefDataStore: PrefDataStoreIf,
    open val rssiRepo: WsnDeviceRssiRepo,
    open val devRepo: WsnDeviceRepo,
    open  val rssiHisRepo: WsnRssiHisRepo
) : BaseAppViewModel(app, prefDataStore) {

    fun observerFilterDto(afterFilterChanged: () -> Unit = {}){

        //这里观察过滤内容，当过滤内容变化时，重新过滤，
        //注意在 Compose 的导航图中，通过 NavBackStackEntry 获取 ViewModel 实例,否则 ‌生命周期管理冲突‌ 会导致多次执行init
        //val navBackStackEntry = remember { navController.currentBackStackEntry }
        //val viewModel: WsnMapViewModel = navBackStackEntry?.let { hiltViewModel(it) } ?: hiltViewModel()
        prefDataStore.getFilterDto().map { result ->
            result?.let {
                _filterState.update { result }
                afterFilterChanged()
            }
        }.launchIn(viewModelScope)
    }

    open fun clearAllData() {
        viewModelScope.launch {
            FhcFlowEventBus.publish( FlowEventBusData(EventType.ClearAllData, null))

            rssiRepo.deleteAllData("")
            devRepo.deleteAll("")
            rssiHisRepo.deleteAll( "")
//            updateFilterDto(FilterDto())
        }
    }



   protected val _filterState = MutableStateFlow(FilterDto())
    val filterState: StateFlow<FilterDto> = _filterState.asStateFlow()

    fun updateFilterDto(newValue: FilterDto) =  viewModelScope.launch {
        prefDataStore.saveFilterDto(newValue)
        _filterState.update { newValue.copy() }
    }

    /**
     * Filter line and device
     *
     * 当过滤设备ID为空时，恢复显示所有设备和连线。
     * 当输入过滤条件时，按空白字符分割成数组并进行大小写不敏感的匹配。line中包含任何设备ID的line都会被保留。
     * 收集line所有匹配的设备ID（包括line的起点和终点）。
     * 根据收集到的设备ID过滤设备列表。
     */
    fun <T : WsnDeviceRssiDto> filterLine(deviceList: List<T>): MutableList<T> {
        val lineList = deviceList.filter { lineDto ->
            if(_filterState.value.isFilterDevIds && _filterState.value.isFilterRssi) {
                isDeviceIdMatch(lineDto) && isRssiMatch(lineDto)
            }else if(_filterState.value.isFilterDevIds) {
                isDeviceIdMatch(lineDto)
            }else if(_filterState.value.isFilterRssi) {
                isRssiMatch(lineDto)
            }else{
                true
            }
        }
        return  lineList.toMutableList()
    }

    // 设备ID匹配逻辑
    protected fun isDeviceIdMatch(lineDto:  WsnDeviceRssiDto): Boolean {
        val state = _filterState.value
        val devIds = state.devIds.trim()
        if (devIds.isEmpty()) return true
        val arr = devIds.split("\\s+".toRegex()).filter { it.isNotEmpty() }
        return arr.any { lineDto.fromDevId.contains(it, ignoreCase = true)  ||  lineDto.toDevId.contains(it, ignoreCase = true) }
    }

    // RSSI匹配逻辑
    protected fun isRssiMatch(lineDto:  WsnDeviceRssiDto): Boolean {
        val state = _filterState.value
        return lineDto.rssi >= state.rssiRangeMin.toInt() && lineDto.rssi <= state.rssiRangeMax.toInt()
    }
}
